package com.heima.wemedia.service.impl;

import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.green20220302.Client;
import com.aliyun.green20220302.models.*;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.teautil.models.RuntimeOptions;
import com.heima.wemedia.bean.ImageCheckResult;
import com.heima.wemedia.bean.TextCheckResult;
import com.heima.wemedia.config.AliYunGreenConfig;
import com.heima.wemedia.service.GreenService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Service
@Slf4j
public class GreenServiceImpl implements GreenService {
    @Resource
    private AliYunGreenConfig aliYunGreenConfig;
    @Resource
    private Client client;
    public static Map<String, DescribeUploadTokenResponseBody.DescribeUploadTokenResponseBodyData> tokenMap = new HashMap<>();
    //服务是否部署在vpc上
    public static boolean isVPC = false;

    @Override
    public TextCheckResult textCheck(String text) {

        Map<String, Object> textMap = MapUtil.<String, Object>builder()
                .put("content", text)
                .build();
        TextModerationPlusRequest textModerationPlusRequest = new TextModerationPlusRequest();
        // 检测类型
        textModerationPlusRequest.setService(aliYunGreenConfig.getTextService());
        textModerationPlusRequest.setServiceParameters(JSONUtil.toJsonStr(textMap));

        try {
            TextModerationPlusResponse response = client.textModerationPlus(textModerationPlusRequest);
            if (response.getStatusCode() == 200) {
                TextModerationPlusResponseBody result = response.getBody();
                if (200 == result.getCode()) {
                    TextModerationPlusResponseBody.TextModerationPlusResponseBodyData data = result.getData();
                    return TextCheckResult.builder()
                            .riskLevel(data.getRiskLevel())
                            .confidenceList(CollStreamUtil.toList(data.getResult(), TextModerationPlusResponseBody.TextModerationPlusResponseBodyDataResult::getConfidence))
                            .riskWordsList(CollStreamUtil.toList(data.getResult(), TextModerationPlusResponseBody.TextModerationPlusResponseBodyDataResult::getRiskWords))
                            .labelList(CollStreamUtil.toList(data.getResult(), TextModerationPlusResponseBody.TextModerationPlusResponseBodyDataResult::getLabel))
                            .build();
                }
            }
        } catch (Exception e) {
            log.error("文件检测失败！text = {}", text, e);
        }

        return TextCheckResult.builder().build();
    }

    @Override
    public ImageCheckResult imageCheck(String imagePath) {
            RuntimeOptions runtime = new RuntimeOptions();

            try {
                String bucketName = null;
                DescribeUploadTokenResponseBody.DescribeUploadTokenResponseBodyData uploadToken = tokenMap.get(this.aliYunGreenConfig.getEndpoint());
                //获取文件上传token
                if (uploadToken == null || uploadToken.expiration <= System.currentTimeMillis() / 1000) {
                    DescribeUploadTokenResponse tokenResponse = this.client.describeUploadToken();
                    uploadToken = tokenResponse.getBody().getData();
                    bucketName = uploadToken.getBucketName();
                }
                //上传文件请求客户端
                OSS ossClient = this.getOssClient(uploadToken, isVPC);

                //上传文件
                String objectName = uploadFile(ossClient, imagePath, uploadToken);

                // 检测参数构造。
                Map<String, String> serviceParameters = new HashMap<>();
                //文件上传信息
                serviceParameters.put("ossBucketName", bucketName);
                serviceParameters.put("ossObjectName", objectName);
                serviceParameters.put("dataId", UUID.randomUUID().toString());

                ImageModerationRequest request = new ImageModerationRequest();
                // 图片检测service：内容安全控制台图片增强版规则配置的serviceCode，示例：baselineCheck
                // 支持service请参考：https://help.aliyun.com/document_detail/467826.html?0#p-23b-o19-gff
                request.setService(this.aliYunGreenConfig.getImageService());
                request.setServiceParameters(JSONUtil.toJsonStr(serviceParameters));

                //校验
                ImageModerationResponse response = this.client.imageModerationWithOptions(request, runtime);

                if (response.getStatusCode() == 200) {
                    ImageModerationResponseBody body = response.getBody();
                    if (body.getCode() == 200) {
                        ImageModerationResponseBody.ImageModerationResponseBodyData data = body.getData();
                        return ImageCheckResult.builder()
                                .riskLevel(data.getRiskLevel())
                                .confidenceList(CollStreamUtil.toList(data.getResult(), ImageModerationResponseBody.ImageModerationResponseBodyDataResult::getConfidence))
                                .labelList(CollStreamUtil.toList(data.getResult(), ImageModerationResponseBody.ImageModerationResponseBodyDataResult::getLabel))
                                .descriptionList(CollStreamUtil.toList(data.getResult(), ImageModerationResponseBody.ImageModerationResponseBodyDataResult::getDescription))
                                .build();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return ImageCheckResult.builder().build();
        }

        /**
         * 上传文件到OSS
         */
        public String uploadFile(OSS ossClient, String imagePath, DescribeUploadTokenResponseBody.DescribeUploadTokenResponseBodyData tokenData) throws Exception {
            String[] split = imagePath.split("\\.");
            String objectName;
            if (split.length > 1) {
                objectName = tokenData.getFileNamePrefix() + UUID.randomUUID() + "." + split[split.length - 1];
            } else {
                objectName = tokenData.getFileNamePrefix() + UUID.randomUUID();
            }

            PutObjectRequest putObjectRequest;
            InputStream inputStream = null;
            if (StrUtil.startWith(imagePath, "http")) {
                //网络图片
                inputStream = HttpRequest.get(imagePath)
                        .timeout(this.aliYunGreenConfig.getConnectTimeout())
                        .execute()
                        .bodyStream();
                putObjectRequest = new PutObjectRequest(tokenData.getBucketName(), objectName, inputStream);
            } else {
                //本地图片
                putObjectRequest = new PutObjectRequest(tokenData.getBucketName(), objectName, new File(imagePath));
            }

            //上传文件
            ossClient.putObject(putObjectRequest);
            //关闭流
            IoUtil.close(inputStream);
            return objectName;
        }

        /**
         * 创建上传文件请求客户端
         */
        public OSS getOssClient(DescribeUploadTokenResponseBody.DescribeUploadTokenResponseBodyData tokenData, boolean isVPC) {
            //注意，此处实例化的client请尽可能重复使用，避免重复建立连接，提升检测性能。
            if (isVPC) {
                return new OSSClientBuilder().build(tokenData.ossInternalEndPoint, tokenData.getAccessKeyId(), tokenData.getAccessKeySecret(), tokenData.getSecurityToken());
            }
            return new OSSClientBuilder().build(tokenData.ossInternetEndPoint, tokenData.getAccessKeyId(), tokenData.getAccessKeySecret(), tokenData.getSecurityToken());
        }
    }

